'use strict';

const Service = require('egg').Service;

const ConnectOption = require('../oltmodules/ConnectOption');
const ZTEOLT = require('../oltmodules/ZTEOLT');
const HWOLT = require('../oltmodules/HuaWeiOLT');
const XDOLT = require('../oltmodules/XinDeOLT');
const ulid = require('../public/ulid');
const snmp = require('net-snmp');
const XGLOLT = require('../oltmodules/XinGeLinOLT');
const path = require('path');
const fs = require('fs');
const mineType = require('mime-types');
const FTPClient = require('../public/FTPClient');
class OltService extends Service {
  async snmpTestConnect(options) {
    try {
      const result = await TestConnect(options,this.ctx);
      return result;
    } catch (error) {
      return false;
    }
  }
  async telnetTestConnect(options) {
    try {
      let result;
      const option = new ConnectOption(
        options.host,
        '',
        '',
        162,
        true,
        true,
        options.tPort,
        options.managementPassword,
        options.username,
        options.password,
        options.systemName,
        '',
        '',
      );
      switch (options.oltType) {
        case 'FIBERHOME': {
          break;
        }
        case 'OPTICTIMES': {
          const xd = new XDOLT(option);
          result = await xd.XDTestConnection();
          break;
        }
        case 'ZTE': {
          const zte = new ZTEOLT(option);
          result = await zte.ZTETestConnection();
          break;
        }
        case 'HUAWEI': {
          const hw = new HWOLT(option);
          result = await hw.HWTestConnection();
          break;
        }
        case 'XINGELIN': {
          const xgl = new XGLOLT(option);
          result = await xgl.XGLTestConnection();
          break;
        }
        default:
          break;
      }
      return result;
    } catch (error) {
      return false;
    }
  }
  async refresh(params) {
    // const oltResult = await this.ctx.model.Olt.findOne({
    //   where: {
    //     id: params.OltId
    //   },
    // });
    let oltResult = await this.ctx.service.Common.getOltInfo(params.OltId);
    let msg = '';
    if (oltResult.oltType == 'OPTICTIMES') {
      var onuProfileResult = await onuProfileRefresh(params.OltId, this);
      if (onuProfileResult.flag == false) {
        msg += onuProfileResult.msg;
      }
    }
    if (oltResult.oltType == 'ZTE') {
      var onuProfileResult = await onuProfileRefresh(params.OltId, this);
      const dbaProfileResult = await dbaProfileRefresh(params.OltId, this);
      if (onuProfileResult.flag == false) {
        msg += onuProfileResult.msg;
      }
      if (dbaProfileResult.flag == false) {
        msg += dbaProfileResult.msg;
      }
    }
    if (oltResult.oltType == 'HUAWEI') {
      var lineProfileResult = await lineProfileRefresh(params.OltId, this);
      const srvprofileResult = await srvProfileRefresh(params.OltId, this);
      if (lineProfileResult.flag == false) {
        msg += lineProfileResult.msg;
      }
      if (srvprofileResult.flag == false) {
        msg += srvprofileResult.msg;
      }
    }
    if (oltResult.oltType == 'XINGELIN') {
      var lineProfileResult = await lineProfileRefresh(params.OltId, this);
      if (lineProfileResult.flag == false) {
        msg += lineProfileResult.msg;
      }
    }
    // const vlanTableResult = await vlanTableRefresh(params.OltId, this);
    const ponResult = await ponRefresh(params.OltId, this);
    const cardResult = await cardRefresh(params.OltId, this);
    const uplinkResult = await uplinkRefresh(params.OltId, this);
    const macResult = await macRefresh(params.OltId, this);
    // if (vlanTableResult.flag == false) {
    //   msg += vlanTableResult.msg;
    // }
    if (ponResult.flag == false) {
      msg += ponResult.msg;
    }
    if (cardResult.flag == false) {
      msg += cardResult.msg;
    }
    if (uplinkResult.flag == false) {
      msg += uplinkResult.msg;
    }
    if (macResult.flag == false) {
      msg += macResult.msg;
    }
    return msg;
  }
  async oltrefresh(params) {
    let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    // 先通过命令去拿到团体名
    let communityArr = [];
    const result = {
      msg: '',
    };
    try {
      switch (oltInformation.oltType) {
        case 'FIBERHOME':
          break;
        case 'OPTICTIMES':
          const xd = new XDOLT(options);
          communityArr = await xd.GetCommunity_XD(this);
          break;
        case 'ZTE':
          const zte = new ZTEOLT(options);
          communityArr = await zte.GetCommunity_ZTE(this);
          break;
        case 'HUAWEI':
          const hw = new HWOLT(options);
          communityArr = await hw.GetCommunity_HW(this);
          break;
        case 'XINGELIN':
          const xgl = new XGLOLT(options);
          communityArr = await xgl.GetCommunity_XGL(this);
          break;
      }
    } catch (error) {
      result.msg = 'refresh fail';
      return result;
    }
    if (communityArr.length > 0) {
      if (oltInformation.oltType == 'XINGELIN') {
        options.community = communityArr[0].community;
      } else {
        options.community = communityArr[0];
      }
    }
    // 通过snmp拿到olt信息
    let oltInfo;
    try {
      switch (oltInformation.oltType) {
        case 'FIBERHOME':
          break;
        case 'OPTICTIMES':
          const xd = new XDOLT(options);
          oltInfo = await xd.getOltInformation();
          break;
        case 'ZTE':
          const zte = new ZTEOLT(options);
          oltInfo = await zte.getOltInformation(oltInformation.oltHardVersion,this);
          break;
        case 'HUAWEI':
          const hw = new HWOLT(options);
          oltInfo = await hw.getOltInformation(oltInformation.MCIndex,this);
          break;
        case 'XINGELIN':
          const xgl = new XGLOLT(options);
          oltInfo = await xgl.getOltInformation();
      }
    } catch (error) {
      result.msg = 'refresh fail';
      return result;
    }
    if (communityArr.length > 0) {
      let ro,
        rw;
      if (oltInformation.oltType == 'XINGELIN') {
        ro = communityArr[0].community;
        rw = communityArr[1].community;
      } else if (oltInformation.oltType == 'HUAWEI') {
        const arr = [];
        communityArr.forEach(item => {
          if (item.indexOf('RZ') != -1) {
            arr.push(item);
          }
        });
        ro = arr[0];
        rw = arr[1];
      } else {
        ro = communityArr[0];
        rw = communityArr[1];
      }
      if (communityArr.length == 2) {
        const input = {
          id: params.OltId,
          systemName: oltInfo.systemName,
          serialNumber: oltInfo.serialNumber,
          macAddress: oltInfo.macAddress,
          softwareCreatedTime: oltInfo.softwareCreatedTime,
          systemTime: oltInfo.systemTime,
          runningTime: (oltInfo.runningTime / 100 / 3600).toFixed(2),
          snmpReadOnlyCommunity: ro,
          snmpReadWriteCommunity: rw,
          cpuUsage: oltInfo.cpuUsage,
          memoryUsage: oltInfo.memoryUsage,
          licenseLimit: oltInfo.licenseLimit,
          licenseTime: oltInfo.licenseTime,
          oltHardVersion: oltInfo.hardwareVersion,
          oltSoftwareVersion: oltInfo.softwareVersion,
        };
        await this.ctx.model.Olt.updateOne({_id: params.OltId}, {
          $set: {
            systemTime:input.systemTime,
            cpuUsage:input.cpuUsage,
            memoryUsage:input.memoryUsage,
          }
        });
      } else {
        const input = {
          id: params.OltId,
          systemName: oltInfo.systemName,
          serialNumber: oltInfo.serialNumber,
          macAddress: oltInfo.macAddress,
          softwareCreatedTime: oltInfo.softwareCreatedTime,
          systemTime: oltInfo.systemTime,
          runningTime: (oltInfo.runningTime / 100 / 3600).toFixed(2),
          snmpReadOnlyCommunity: ro,
          snmpReadWriteCommunity: rw,
          cpuUsage: oltInfo.cpuUsage,
          memoryUsage: oltInfo.memoryUsage,
          licenseLimit: oltInfo.licenseLimit,
          licenseTime: oltInfo.licenseTime,
          oltHardVersion: oltInfo.hardwareVersion,
          oltSoftwareVersion: oltInfo.softwareVersion,
        };
        await this.ctx.model.Olt.updateOne({_id: params.OltId}, {
          $set: {
            systemTime:input.systemTime,
            cpuUsage:input.cpuUsage,
            memoryUsage:input.memoryUsage,
          }
        });
      }
    } else {
      const input = {
        id: params.OltId,
        systemName: oltInfo.systemName,
        serialNumber: oltInfo.serialNumber,
        macAddress: oltInfo.macAddress,
        softwareCreatedTime: oltInfo.softwareCreatedTime,
        systemTime: oltInfo.systemTime,
        runningTime: (oltInfo.runningTime / 100 / 3600).toFixed(2),
        cpuUsage: oltInfo.cpuUsage,
        memoryUsage: oltInfo.memoryUsage,
        licenseLimit: oltInfo.licenseLimit,
        licenseTime: oltInfo.licenseTime,
        oltHardVersion: oltInfo.hardwareVersion,
        oltSoftwareVersion: oltInfo.softwareVersion,
      };
      await this.ctx.model.Olt.updateOne({_id: params.OltId}, {
        $set: {
          systemTime:input.systemTime,
          cpuUsage:input.cpuUsage,
          memoryUsage:input.memoryUsage,
        }
      });
    }
    result.msg = 'refresh successful';
    return result;
  }
  async cardrefresh(params,oltInformation) {
    const result = await cardRefresh(params.OltId,oltInformation, this);
    return result;
  }
  async ponportsrefresh(params,oltInformation) {
    const result = await ponRefresh(params.OltId,oltInformation, this);
    return result;
  }
  async uplinkrefresh(params,oltInformation) {
    const result = await uplinkRefresh(params.OltId,oltInformation, this);
    return result;
  }
  // async vlanrefresh(params) {
  //   const result = await vlanTableRefresh(params.OltId, this);
  //   return result;
  // }
  async macrefresh(oltInformation) {
    const result = await macRefresh(oltInformation, this);
    return result;
  }
  async listAll(tid) {
    const result = await this.ctx.model.Olt.find({
      tid,
    });
    return result;
  }
  async save(params) {
    const result = await OltSave(params.OltId, this);
    return result;
  }
  async backup(params) {
    const result = {
      msg: '',
      data: {},
    };
    try {
      console.log('service.backup')
      let oltInformation = await this.ctx.service.common.getOltInfo(params.id);
      const options = new ConnectOption(
        oltInformation.oltIP,
        oltInformation.initCommunity,
        oltInformation.snmpUDPPort,
        162,
        true,
        true,
        oltInformation.telnetTCPPort,
        oltInformation.oltManagementPassword,
        oltInformation.oltTelnetUsername,
        oltInformation.oltTelnetPassword,
        oltInformation.systemName,
        oltInformation.RZUsername,
        oltInformation.RZPassword,
        oltInformation.telnetProxySwitch
      );
      console.log('service->oltinfo:',oltInformation.oltType)
      let flag = false;
      const connectFlag = await FTPClient.connect({
        host: this.app.config.ftpIP,
        port: 21,
        user: this.app.config.ftpUsername,
        password: this.app.config.ftpPassword,
        timeout: 50000,
      });
      if (!connectFlag) {
        console.log('can not connect ftp server',this.app.config.ftpIP)
        result.msg = 'can not connect ftp server';
        return result;
      }
      console.log('ftp服务器连接成功')
      switch (oltInformation.oltType) {
        case 'XINGELIN': {
          break;
        }
        case 'OPTICTIMES': {
          break;
        }
        case 'ZTE': {
          await FTPClient.mkdir(params.id, true); // 中兴需要将文件传到id目录下
          const zte = new ZTEOLT(options);
          console.log('我马上要调用中兴备份的方法了')
          flag = await zte.oltBackUp(
            params.id,
            oltInformation.oltHardVersion,
            this
          );
          break;
        }
        case 'HUAWEI': {
          const hw = new HWOLT(options);
          flag = await hw.oltBackUp(params.id, 'NONE', this);
          // flag = await hw.oltBackUp(params.id, oltInformation.oltHardVersion, this);
          break;
        }
        default:
          console.log('不支持此品牌设备');
          break;
      }
      console.log('调用方法返回信息:',JSON.stringify(flag));
      if (flag.flag) {
        // 不同的设备需要匹配不懂的路径规则
        const rules = {
          HUAWEI(params) {
            console.log('进来了 华为的方法');
            const source = `${params.id}_startrun.cfg`;
            const src = path.join(
              __dirname,
              '../public/homedir',
              `${params.id}_startrun.cfg`
            );
            const filename = 'startrun.cfg';
            return {
              src,
              filename,
              source,
            };
          },
          ZTE(params) {
            const src = path.join(
              __dirname,
              `../public/homedir/${params.id}`,
              'startrun.dat'
            );
            const filename = 'startrun.dat';
            const source = `${params.id}/${filename}`;
            return {
              src,
              filename,
              source,
            };
          },
        };
        console.log('function=', rules[oltInformation.oltType]);
        const {
          src,
          filename,
          source
        } = rules[oltInformation.oltType](params);
         console.log('rules返回', src, filename, source);
        if (connectFlag) {
          try {
            console.log('DOWNLOAD')
            await FTPClient.download(source, src);
            console.log('DELETE')
            await FTPClient.delete(source);
            console.log('CLOSE')
            await FTPClient.close();          
          } catch (error) {
            console.log('错误:',error)
          }
        } else {
          result.msg = 'FTP connect fail';
          return result;
        }
        // if (oltInformation.oltType === 'HUAWEI') {
        //   src = path.join(__dirname, '../public/homedir', `${params.id}_startrun.cfg`);
        //   await FTPClient.download(`${params.id}_startrun.cfg`, src);
        //   await FTPClient.delete(`${params.id}_startrun.cfg`);
        //   filename = 'startrun.cfg';
        // } else {
        //   src = path.join(__dirname, `../public/homedir/${params.id}`, 'startrun.dat');
        //   filename = 'startrun.dat';
        //   if (connectFlag) {
        //     const source = `${params.id}/${filename}`;
        //     console.log(source, src);
        //     await FTPClient.download(source, src);
        //     await FTPClient.delete(source);
        //   }
        // }
        // await FTPClient.close();
        // 这里需要从ftp服务器上下载文件，然后转base64传给前端
        const str = fs.readFileSync(src, 'utf8');
        const b = Buffer.from(str);
        const base64 =
          'data:' + mineType.lookup(src) + ';base64,' + b.toString('base64');
        fs.unlinkSync(src);
        result.data = {
          filename,
          content: base64,
        };
        result.msg = flag.msg;
        return result;
      }
      result.msg = flag.msg;
      return result;
    } catch (error) {
      console.log('报错了====================',error)
      return result;
    }
  }
  async upload(params) {
    const result = {
      msg: '',
    };
    const file = params.file;
    let oltInformation = await this.ctx.service.common.getOltInfo(params.id);
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    // 上传文件
    let filePath;
    if (oltInformation.oltType === 'HUAWEI') {
      filePath = path.join(
        __dirname,
        '../public/homedir',
        `${params.id}_startrun.cfg`
      );
    } else {
      filePath = path.join(
        __dirname,
        '../public/homedir',
        params.id,
        'startrun.dat'
      ); // 上传路径
    }
    // const { dir } = path.parse(filePath);
    // fs.mkdirSync(dir, { recursive: true });
    // const reg = /data:(.*)base64,(.*)/;
    // const base64 = reg.exec(params.data); // 提取文件内容
    // const dataBuffer = Buffer.from(base64[2], 'base64'); // 把base64码转成buffer对象，
    // // 二进制文件存在服务器
    // fs.writeFileSync(filePath, dataBuffer);
    // 这里需要把文件上传到ftp服务器上，然后调用olt去ftp服务器上获取
    const connectFlag = await FTPClient.connect({
      host: this.app.config.ftpIP,
      port: 21,
      user: this.app.config.ftpUsername,
      password: this.app.config.ftpPassword,
      timeout: 50000,
    });
    let dest;
    if (connectFlag) {
      dest =
        oltInformation.oltType === 'HUAWEI' ?
        `${params.id}_startrun.cfg` :
        `${params.id}/startrun.dat`;
      if (oltInformation.oltType !== 'HUAWEI') {
        console.log('mkdir', params.id);
        const fileList = await FTPClient.list();
        const i = fileList.findIndex(item => {
          return item.type === 'd' && item.name === params.id;
        });
        i === -1 && (await FTPClient.mkdir(params.id));
      }
      await FTPClient.upload(file.filepath, dest);
    } else {
      result.msg = 'can not connection ftp server';
      return result;
    }
    // 获取olt信息
    let uploadResult;
    let zte,
      hw;
    switch (oltInformation.oltType) {
      case 'FIBERHOME':
        uploadResult = {
          flag: false,
          data: 'not support this olt',
        };
        break;
      case 'OPTICTIMES':
        uploadResult = {
          flag: false,
          data: 'not support this olt',
        };
        break;
      case 'ZTE':
        zte = new ZTEOLT(options);
        uploadResult = await zte.oltRestore(
          params.id,
          oltInformation.oltHardVersion,
          'startrun.dat',
          this
        );
        break;
      case 'HUAWEI':
        hw = new HWOLT(options);
        uploadResult = await hw.oltRestore(
          params.id,
          'NONE',
          params.id + '_startrun.cfg',
          this
        );
        // uploadResult = await hw.oltRestore(params.id, oltInformation.oltHardVersion, params.id + '_startrun.cfg', this);
        break;
      default:
        console.log('不支持此品牌olt');
    }
    if (uploadResult.flag) {
      // fs.unlinkSync(filePath);
      await FTPClient.delete(dest);
      // result.msg = uploadResult.data;
      // return result;
    }
    // fs.unlinkSync(filePath);
    result.msg = uploadResult.data;
    return result;
  }
  async active(id) {
    let oltInformation = await this.ctx.service.common.getOltInfo(id);
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    const result = {
      msg: '',
      flag: true,
    };
    try {
      const me = this;
      switch (oltInformation.oltType) {
        case 'OPTICTIMES': {
          break;
        }
        case 'ZTE': {
          break;
        }
        case 'HUAWEI': {
          const hw = new HWOLT(options);
          await hw.activeOlt('NONE', me);
          break;
        }
        case 'XINGELIN': {
          break;
        }
        default:
          break;
      }
      result.msg = 'olt active successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'olt active fail,' + error;
      result.flag = false;
      return result;
    }
  }
  async reboot(id) {
    let oltInformation = await this.ctx.service.common.getOltInfo(id);
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    const result = {
      msg: '',
      flag: true,
    };
    try {
      const me = this;
      switch (oltInformation.oltType) {
        case 'OPTICTIMES': {
          break;
        }
        case 'ZTE': {
          const zte = new ZTEOLT(options);
          await zte.rebootOlt(oltInformation.oltHardVersion, me);
          break;
        }
        case 'HUAWEI': {
          const hw = new HWOLT(options);
          await hw.rebootOlt('NONE', me);
          break;
        }
        case 'XINGELIN': {
          break;
        }
        default:
          break;
      }
      result.msg = 'olt reboot successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'olt reboot fail,' + error;
      result.flag = false;
      return result;
    }
  }
  async oltInit(params) {
    const result = {
      msg: '',
      flag: false,
    };
    let oltInformation = await this.ctx.service.common.getOltInfo(params.id);
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.snmpReadOnlyCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    try {
      switch (oltInformation.oltType) {
        case 'OPTICTIMES':
          break;
        case 'XINGELIN':
          break;
        case 'ZTE':
          const zte = new ZTEOLT(options);
          await zte.oltInit(oltInformation.oltHardVersion, this);
          break;
        case 'HUAWEI':
          const hw = new HWOLT(options);
          await hw.oltInit(params.vlan, oltInformation.oltHardVersion, this);
          const vlanResult = await this.ctx.model.Vlan.findAll({
            where: {
              oltId: params.id
            },
          });
          const vlanArr = [];
          vlanResult.forEach(element => {
            vlanArr.push(element.VlanID);
          });
          if (vlanArr.indexOf('' + params.vlan) == -1) {
            await this.ctx.model.Vlan.create({
              id: ulid.ulid(),
              tid: params.tid,
              oltId: params.id,
              VlanID: params.vlan,
            });
          }
          break;
      }
      result.msg = 'oltinit successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'oltinit fail,' + error;
      result.flag = false;
      return result;
    }
  }
  async addOltMandate(tid) {
    const result = {
      msg: '',
      flag: false,
    };
    const tenantResult1 = await this.ctx.model.TenantAdmin.findOne({
      where: {
        id: tid
      },
    });
    const diffDays = diffDate(Date.now(), tenantResult1.authorizedEndTime);
    if (diffDays < 0) {
      await this.ctx.model.TenantAdmin.update({
        state: false
      }, {
        where: {
          id: tid
        },
      });
    }
    const tenantResult2 = await this.ctx.model.TenantAdmin.findOne({
      where: {
        id: tid
      },
    });
    const oltList = await this.ctx.model.Olt.findAndCountAll({
      where: {
        tid
      },
    });
    if (tenantResult2.state == false) {
      if (oltList.count >= 1) {
        result.msg = 'You can only add 1 OLT';
        result.flag = false;
      } else {
        result.flag = true;
      }
    } else if (tenantResult2.state == true) {
      if (oltList.count >= tenantResult2.users) {
        result.msg = `You can only add ${tenantResult2.users} OLT`;
        result.flag = false;
      } else {
        result.flag = true;
      }
    }
    return result;
  }
  // ---------------------------------------------------------------------------------------
  async list(params) {
    console.time('list')
    const result = {
      count: '',
      msg: '',
    };
    result.count = await this.ctx.model.Olt.find({
      tid: params.tid
    }).count(
      '_id'
    );
    result.msg = await this.ctx.model.Olt.find({
        tid: params.tid
      })
      .skip(parseInt((params.page - 1) * params.limit))
      .limit(parseInt(params.limit));
    console.timeEnd('list')
    return result;
  }
  async create(input) {
    const result = {
      msg: '',
      id: '',
    };
    try {
      input._id = ulid.ulid();
      await this.ctx.model.Olt.create(input);
      result.msg = 'olt create successful';
      result.id = input._id;
      return result;
    } catch (error) {
      result.msg = 'olt create fail,' + error;
      return result;
    }
  }
  async edit(params) {
    const result = {
      msg: '',
    };
    try {
      await this.ctx.model.Olt.updateOne({
        _id: params.id
      }, {
        $set: {
          name: params.name,
          oltIP: params.oltIP,
          telnetTCPPort: params.telnetTCPPort,
          oltTelnetUsername: params.oltTelnetUsername,
          oltTelnetPassword: params.oltTelnetPassword,
          oltManagementPassword: params.oltManagementPassword,
          snmpUDPPort: params.snmpUDPPort,
          ACSVlan: params.ACSVlan,
          telnetProxySwitch:params.telnetProxySwitch,
        },
      });
      result.msg = 'edit olt succrssful';
      return result;
    } catch (error) {
      result.msg = 'edit olt fail,' + error;
      return result;
    }
  }
  async delete(params) {
    // 删除很多关于olt的东西，不光只是olt本身
    await this.ctx.model.Card.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.DbaProfile.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.LineProfile.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.OnuList.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.OnuProfile.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.PonPorts.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.SpeedProfile.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.UplinkPorts.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.Vlan.deleteMany({
      oltId: params.id
    })
    await this.ctx.model.OnuFind.deleteMany({
      oltId: params.id
    })
    return await this.ctx.model.Olt.deleteOne({
      _id: params.id
    });
  }
  async oltsingle(params) {
    const result = await this.ctx.model.Olt.findOne({
      _id: params.OltId
    });
    return result;
  }
  //---------------------------------------------------------------------
  // 获取olt状态
  async getOltStatus(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const oltStatus = await isOnline(oltInformation,this);
      console.log('获取olt状态', oltStatus);
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          onlineState: oltStatus
        }
      });
      if (oltStatus == true) {
        result.flag = oltStatus;
        result.msg = 'olt is Online';
      } else {
        result.flag = oltStatus;
        result.msg = 'olt is Offline';
      }
      return result;
    } catch (error) {
      result.flag = false;
      result.msg = 'getOltStatus fail,' + error;
      return result;
    }
  }
  // 获取olt系统名和运行时间
  async getSystemName(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const oltInfo = await snmpGetSystenName.call(this,oltInformation);
      const time = await formatSeconds(oltInfo.runningTime);
      console.log('getSystemName插库', new Date());
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          systemName: oltInfo.systemName,
          runningTime: time
        }
      });
      result.flag = true;
      result.msg = 'successful';
      return result;
    } catch (error) {
      result.flag = false;
      result.msg = 'fail,' + error;
      return result;
    }
  }
  // 创建RZAdmin
  async createRZAdmin(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      await setRZAdmin(oltInformation, this);
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          RZUsername: 'rzadmin',
          RZPassword: 'rzadmin123'
        }
      });
      result.msg = 'successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取Version
  async getOltVersion(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const oltVersionResult = await getOltVersion(oltInformation, this);
      console.log('getOltVersion插库', new Date());
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          oltHardVersion: oltVersionResult.oltHardVersion,
          oltHardwareVersion: oltVersionResult.oltHardwareVersion,
          oltSoftwareVersion: oltVersionResult.oltSoftwareVersion,
          MCIndex: oltVersionResult.MCIndex,
        },
      });
      result.flag = true;
      result.msg = 'successful';
      return result;
    } catch (error) {
      result.flag = false;
      result.msg = 'fail,' + error;
      return result;
    }
  }
  // 获取oltInformation
  async getOltInformation(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const oltVersionResult = await getOltInformation(oltInformation, this);
      const oltStatus = await isOnline(oltInformation,this);
      console.log('getOltInformation插库', new Date());
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          cpuUsage: oltVersionResult.cpuUsage,
          memoryUsage: oltVersionResult.memoryUsage,
          MCIndex: oltVersionResult.MCIndex,
          systemTime: oltVersionResult.systemTime,
          onlineState: oltStatus
        },
      });
      result.flag = true;
      result.msg = 'successful';
      return result;
    } catch (error) {
      result.flag = false;
      result.msg = 'fail,' + error;
      return result;
    }
  }
  // 获取olt温度
  async getOltTemperature(params) {
    const result = {
      msg: '',
      flag: '',
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const oltTemperature = await getOltTemperature(oltInformation, this);
      console.log('getOltTemperature插库', new Date());
      await this.ctx.model.Olt.updateOne({
        _id: params.OltId
      }, {
        $set: {
          temperature: oltTemperature
        }
      });
      result.msg = 'getTemperature successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getTemperature fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取cardInformation
  async getCardInformation(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const cardInformation = await getCardInformation(oltInformation, this);
      console.log('getCardInformation插库', new Date());
      const arr = [];
      for (let i = 0; i < cardInformation.length; i++) {
        arr.push(cardInformation[i].slot);
        const cardResult = await this.ctx.model.Card.findOne({
          oltId: params.OltId,
          slot: cardInformation[i].slot,
        });
        if (cardResult == null) {
          cardInformation[i]._id = ulid.ulid();
          cardInformation[i].oltId = params.OltId;
          await this.ctx.model.Card.create(cardInformation[i]);
        } else {
          await this.ctx.model.Card.updateOne({
            _id: cardResult._id,
            oltId: params.OltId
          }, {
            $set: {
              slot: cardInformation[i].slot,
              type: cardInformation[i].type,
              realType: cardInformation[i].realType,
              port: cardInformation[i].port,
              sw: cardInformation[i].sw,
              status: cardInformation[i].status,
            },
          });
        }
      }
      await this.ctx.model.Card.deleteMany({
        slot: {
          $nin: arr
        },
        oltId: params.OltId,
      });
      result.msg = 'getCardInformation successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getCardInformation fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取PonPorts和UplinkPorts
  async getPonPortsAndUplinkPorts(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const portlist = await getPonPortsAndUplinkPorts.call(this,oltInformation);
      console.log('getPonPortsAndUplinkPorts插库', new Date());
      const ponPorts = [];
      const uplinkPorts = [];
      for (var i = 0; i < portlist.ponPortsArr.length; i++) {
        ponPorts.push(portlist.ponPortsArr[i].port);
        const ponPortResult = await this.ctx.model.PonPorts.findOne({
          oltId: params.OltId,
          port: portlist.ponPortsArr[i].port,
        });
        if (ponPortResult == null) {
          portlist.ponPortsArr[i]._id = ulid.ulid();
          portlist.ponPortsArr[i].oltId = params.OltId;
          await this.ctx.model.PonPorts.create(portlist.ponPortsArr[i]);
        } else {
          await this.ctx.model.PonPorts.updateOne({
            _id: ponPortResult._id,
            oltId: params.OltId
          }, {
            $set: {
              port: portlist.ponPortsArr[i].port,
              adminStatus: portlist.ponPortsArr[i].adminStatus,
              status: portlist.ponPortsArr[i].status,
              p: portlist.ponPortsArr[i].p,
              s: portlist.ponPortsArr[i].s,
            },
          });
        }
      }
      for (var i = 0; i < portlist.uplinkPortsArr.length; i++) {
        uplinkPorts.push(portlist.uplinkPortsArr[i].port);
        const uplinkPortResult = await this.ctx.model.UplinkPorts.findOne({
          oltId: params.OltId,
          port: portlist.uplinkPortsArr[i].port,
        });
        if (uplinkPortResult == null) {
          portlist.uplinkPortsArr[i]._id = ulid.ulid();
          portlist.uplinkPortsArr[i].oltId = params.OltId;
          await this.ctx.model.UplinkPorts.create(portlist.uplinkPortsArr[i]);
        } else {
          await this.ctx.model.UplinkPorts.updateOne({
            _id: uplinkPortResult._id,
            oltId: params.OltId
          }, {
            $set: {
              port: portlist.uplinkPortsArr[i].port,
              adminStatus: portlist.uplinkPortsArr[i].adminStatus,
              status: portlist.uplinkPortsArr[i].status,
              p: portlist.uplinkPortsArr[i].p,
              s: portlist.uplinkPortsArr[i].s,
              speed: portlist.uplinkPortsArr[i].speed,
            },
          });
        }
      }
      await this.ctx.model.PonPorts.deleteMany({
        port: {
          $nin: ponPorts
        },
        oltId: params.OltId,
      });
      await this.ctx.model.UplinkPorts.deleteMany({
        port: {
          $nin: uplinkPorts
        },
        oltId: params.OltId,
      });
      result.msg = 'getPonPortsAndUplinkPorts successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getPonPortsAndUplinkPorts fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取onutype
  async getOltONUProfile(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const onuProfileResult = await getOltONUProfile(oltInformation, this);
      console.log('getOltONUProfile插库', new Date());
      const onuTypeArr = [];
      for (let i = 0; i < onuProfileResult.length; i++) {
        onuTypeArr.push(onuProfileResult[i].Pname);
        const onuTypeResult = await this.ctx.model.OnuProfile.findOne({
          oltId: params.OltId,
          Pname: onuProfileResult[i].Pname,
        });
        if (onuTypeResult == null) {
          onuProfileResult[i]._id = ulid.ulid();
          onuProfileResult[i].oltId = params.OltId;
          await this.ctx.model.OnuProfile.create(onuProfileResult[i]);
        } else {
          await this.ctx.model.OnuProfile.updateOne({
            _id: onuTypeResult._id
          }, {
            $set: {
              Pname: onuProfileResult[i].Pname
            }
          });
        }
      }
      await this.ctx.model.OnuProfile.deleteMany({
        Pname: {
          $nin: onuTypeArr
        },
        oltId: params.OltId,
      });
      result.msg = 'getONUType successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getONUType fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取dbaprofile
  async getOltDBAProfile(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const dbaProfileArr = await getOltDBAProfile(oltInformation, this);
      console.log('getOltDBAProfile插库', new Date());
      const dbaProfiles = [];
      for (let i = 0; i < dbaProfileArr.length; i++) {
        dbaProfiles.push(dbaProfileArr[i].name);
        const dbaProfileResult = await this.ctx.model.DbaProfile.findOne({
          oltId: params.OltId,
          name: dbaProfileArr[i].name,
        });
        if (dbaProfileResult == null) {
          dbaProfileArr[i]._id = ulid.ulid();
          dbaProfileArr[i].oltId = params.OltId;
          await this.ctx.model.DbaProfile.create(dbaProfileArr[i]);
        } else {
          await this.ctx.model.DbaProfile.updateOne({
            _id: dbaProfileResult._id
          }, {
            $set: {
              name: dbaProfileArr[i].name,
              max: dbaProfileArr[i].max,
              type: dbaProfileArr[i].type,
              fbw: dbaProfileArr[i].fbw,
              abw: dbaProfileArr[i].abw
            }
          });
        }
      }
      await this.ctx.model.DbaProfile.deleteMany({
        name: {
          $nin: dbaProfiles
        },
        oltId: params.OltId,
      });
      result.msg = 'getDBAProfile successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getDBAProfile fail,' + error;
      result.flag = false;
      return result;
    }
  }
  /**
   * 由于华为的lineprofile详细信息中只有dbaprofile-id，这个函数就是找到id对应的dbaprofile name
   * @param {*} line 
   * @param {*} dba 
   */
  lineWrap(line,dba){
    let dbaDB = {}
    dba.forEach(item=>{
      dbaDB[item.id.toString()] = item.name;
    })
    line.forEach((value,key,map)=>{
      let length = value.length;
      for(let i=0;i<length;i++){
        value[i].dbaProfile = dbaDB[value[i].dbaProfileID]
      }
    })
    return line;
  }
  // 获取lineprofile
  async getOltLineProfile(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const lineProfileArr = await getOltLineProfile(oltInformation, this);
      let lineList = await getOltLineDetail(lineProfileArr,oltInformation,this); 
      let dbaArr = [];
      if(oltInformation.oltType==='HUAWEI'){
        dbaArr = await getOltDBAProfile(oltInformation,this);
        lineList = this.lineWrap(lineList,dbaArr)
      }
      console.log('getOltLineProfile插库', new Date());
      const lineProfiles = [];
      for (let i = 0; i < lineProfileArr.length; i++) {
        lineProfiles.push(lineProfileArr[i].name);
        const lineProfileResult = await this.ctx.model.LineProfile.findOne({
          oltId: params.OltId,
          name: lineProfileArr[i].name,
        });
        
        if (lineProfileResult == null) {
          lineProfileArr[i]._id = ulid.ulid();
          lineProfileArr[i].oltId = params.OltId;
          lineProfileArr[i].bussinessArr = lineList.get(lineProfileArr[i].name);
          await this.ctx.model.LineProfile.create(lineProfileArr[i]);
        } else {
          await this.ctx.model.LineProfile.updateOne({
            _id: lineProfileResult._id
          }, {
            $set: {
              name: lineProfileArr[i].name,
              bussinessArr:lineList.get(lineProfileArr[i].name)
            }
          });
        }
        
      }
      await this.ctx.model.LineProfile.deleteMany({
        name: {
          $nin: lineProfiles
        },
        oltId: params.OltId,
      });
      result.msg = 'getOltLineProfile successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getOltLineProfile fail,' + error;
      result.flag = false;
      return result;
    }
  }

  //获取remoteprofile
  async getOltRemoteprofile(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      //先获取remote名字列表
      const remoteProfileArr = await getOltRemoteProfile(oltInformation, this);   
      //根据remote名字刷新detail信息
      let remoteList =await getOltRemoteDetail(remoteProfileArr,oltInformation,this);
      //遍历remoteProfileArr进行插库
      console.log('getOltRemoteProfile插库', new Date());
      const remoteProfiles = [];
      for (let i = 0; i < remoteProfileArr.length; i++) {
        remoteProfiles.push(remoteProfileArr[i].name)
        const remoteProfileResult = await this.ctx.model.RemoteProfile.findOne({
          oltId: params.OltId,
          name: remoteProfileArr[i].name,
        })
        let bussinessArr = remoteList.get(remoteProfileArr[i].name);
        if (remoteProfileResult == null) {
          remoteProfileArr[i]._id = ulid.ulid();
          remoteProfileArr[i].oltId = params.OltId;
          remoteProfileArr[i].bussinessArr = bussinessArr;
          await this.ctx.model.RemoteProfile.create(remoteProfileArr[i]);
        } else {
          await this.ctx.model.RemoteProfile.updateOne({
            _id: remoteProfileResult._id
          }, {
            $set: {
              name: remoteProfileArr[i].name,
              bussinessArr:bussinessArr
            }
          });
        }
      }
      //删掉多余的remoteprofile
      await this.ctx.model.RemoteProfile.deleteMany({
        name: {
          $nin: remoteProfiles
        },
        oltId: params.OltId,
      });
      result.msg = 'getOltRemoteProfile successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getOltRemoteProfile fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取oltVlan
  async getOltVlan(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const vlanarr = await getOltVlan(oltInformation, this);
      console.log('getOltVlan插库', new Date());
      const arr = [];
      const oltVlanList = await this.ctx.model.Vlan.find({oltId: params.OltId});
      vlanarr.forEach(vlanOBJ=>{
        if(vlanOBJ.VlanID.indexOf('-')!=-1){
          let [startVlan,endVlan] = vlanOBJ.VlanID.split('-');
          for(let j=startVlan;j<=endVlan;j++){
            arr.push(j.toString());
          }
        }else{
          arr.push(vlanOBJ.VlanID)
        }
      })
      const waitingInsertModels = arr.map(vlanID=>{
        if(oltVlanList.find(model=>model.VlanID===vlanID)===undefined){
          return {
            _id: ulid.ulid(),
                      oltId: params.OltId,
                      VlanID: vlanID,
                      description: '',
                    };
        }else{
          return;
        }
      })
      await this.ctx.model.Vlan.deleteMany({
        VlanID: {
          $nin: arr
        },
        oltId: params.OltId,
      });
      let models = waitingInsertModels.filter(m=>{
        return m!==undefined
      });
      if(models.length>0){
        await this.ctx.model.Vlan.create(models)
      }
      result.msg = 'getOltVlan successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getOltVlan fail,' + error;
      result.flag = false;
      return result;
    }
  }
  //获取Mac
  async getOltMac(params) {
    const result = {
      msg: "",
      flag: false
    }
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const macArr = await getOltMac(oltInformation, this)
      console.log("getOltMac插库", new Date())
      await this.ctx.model.Mac.deleteMany({
        oltId: params.OltId,
      })
      for (var i = 0; i < macArr.length; i++) {
        macArr[i]._id = ulid.ulid();
        macArr[i].oltId = params.OltId;
        await this.ctx.model.Mac.create(macArr[i])
      }
      result.msg = "getOltMac successful"
      result.flag = true
      return result
    } catch (error) {
      result.msg = 'getOltMac fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取speedProfile
  async getOltSpeedProfile(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      const speedProfileArr = await getOltSpeedProfile(oltInformation, this);
      console.log('getOltSpeedProfile插库', new Date());
      const speedProfiles = [];
      for (let i = 0; i < speedProfileArr.length; i++) {
        speedProfiles.push(speedProfileArr[i].name);
        const speedProfileResult = await this.ctx.model.SpeedProfile.findOne({
          oltId: params.OltId,
          name: speedProfileArr[i].name,
        });
        if (speedProfileResult == null) {
          speedProfileArr[i]._id = ulid.ulid();
          speedProfileArr[i].oltId = params.OltId;
          await this.ctx.model.SpeedProfile.create(speedProfileArr[i]);
        } else {
          await this.ctx.model.SpeedProfile.updateOne({
            _id: speedProfileResult._id
          }, {
            $set: {
              name: speedProfileArr[i].name,
              SIR: speedProfileArr[i].SIR,
              PIR: speedProfileArr[i].PIR,
              CBS: speedProfileArr[i].CBS,
              PBS: speedProfileArr[i].PBS,
            },
          });
        }
      }
      await this.ctx.model.SpeedProfile.deleteMany({
        name: {
          $nin: speedProfiles
        },
        oltId: params.OltId,
      });
      result.msg = 'getOltSpeedProfile successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'getOltSpeedProfile fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 设置oltacsvlan
  async setOltAcsVlan(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
      await setOltAcsVlan(oltInformation, this);
      result.msg = 'setOltTr069Vlan successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'setOltTr069Vlan fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取olt中已注册的onulist
  async getRegisteredONUList(params) {
    const result = {
      msg: '',
      flag: false,
    };
    let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
    try {
      console.time('getRegisteredONUList')
      const onuListResult = await getRegisteredONUList(oltInformation, this);
      console.timeEnd('getRegisteredONUList')
      const axistONU = [];
      console.log('获取onulist插库', new Date());
      console.time('获取onulist插库')
      const onuList = await this.ctx.model.OnuList.find({
        oltId:params.OltId,
        tid:params.tid
      })
      const waitingInsertModels = [];
      const waitingDeleteIDs = []
      const onuListArr = []
      onuListResult.forEach(onu => {
        onuListArr.push(onu.onlyindex)
      })
      onuList.forEach(item=>{
        if((onuListResult.find(onu=>item.onlyindex===onu.onlyindex&&item.sn!==onu.sn)) || (onuListArr.indexOf(item.onlyindex) == -1)){
          waitingDeleteIDs.push(item._id)
        }
      });
      let delRes = await this.ctx.model.OnuList.deleteMany({
        _id: {
          $in: waitingDeleteIDs
        },
        oltId: params.OltId,
      });
      onuListResult.forEach(async onuOBJ=>{
        axistONU.push(onuOBJ.onlyindex);
        let onuInDB = onuList.find(onu=>onu.onlyindex===onuOBJ.onlyindex)
        if(onuInDB===undefined){
          //数据库中没有此sn号
          onuOBJ._id = ulid.ulid();
          onuOBJ.oltId = params.OltId;
          onuOBJ.tid = oltInformation.tid;
          onuOBJ.catvstate = null;
          waitingInsertModels.push(onuOBJ);
        }else if(onuInDB.sn===onuOBJ.sn){
          //判断需要更新
          if(onuInDB.ONUname!=onuOBJ.ONUname||onuInDB.status!=onuOBJ.status||onuInDB.PONindex!=onuOBJ.PONindex||onuInDB.ONUindex!=onuOBJ.ONUindex||onuInDB.number!=onuOBJ.number
            ||onuInDB.slot!=onuOBJ.slot||onuInDB.port!=onuOBJ.port||onuInDB.rx!=onuOBJ.Rx||onuInDB.onuType!=onuOBJ.onuType){
              await this.ctx.model.OnuList.updateOne({
                _id: onuInDB._id
              }, {
                $set: {
                  status: onuOBJ.status,
                  oltId: params.OltId,
                  PONIndex: onuOBJ.PONindex,
                  ONUindex: onuOBJ.ONUindex,
                  ONUname:onuOBJ.ONUname,
                  onlyindex: onuOBJ.onlyindex,
                  number: onuOBJ.number,
                  slot: onuOBJ.slot,
                  port: onuOBJ.port,
                  onuType:onuOBJ.onuType,
                  rx:onuOBJ.Rx,
                  catvstate:null
                },
              });
            }
        }
      })
      if(waitingInsertModels.length>0){
        await this.ctx.model.OnuList.create(waitingInsertModels);
      }
      
      console.timeEnd('获取onulist插库')
      result.msg = oltInformation.oltIP+'getRegisteredONUList successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = oltInformation.oltIP+'getRegisteredONUList fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 获取olt中未注册的onufind
  async getUnregisteredONUList(params) {
    const result = {
      msg: '',
      flag: false,
    };
    let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
    try {
      const onuFindResult = await getUnregisteredONUList(oltInformation, this);
      const onufindarr = await sortONUFindIndex(
        oltInformation.oltType,
        oltInformation._id,
        oltInformation.tid,
        onuFindResult,
        this
      );
      console.log('获取onufind插库', new Date());
      await this.ctx.model.OnuFind.deleteMany({
        tid: oltInformation.tid,
        oltId: params.OltId
      });
      await this.ctx.model.OnuFind.create(onufindarr);
      result.msg = oltInformation.oltIP+' getUnregisteredONUList successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = oltInformation.oltIP+' getUnregisteredONUList fail,' + error;
      result.flag = false;
      return result;
    }
  }
  // 给olt中已注册的onu下发acs地址
  async setRegisteredOnuAcsUrl(params) {
    const result = {
      msg: '',
      flag: false,
    };
    try {
      const oltResult = await this.ctx.model.Olt.findOne({
        _id: params.OltId
      });
      const onuResult = await this.ctx.model.OnuList.find({
        oltId: params.OltId,
      });
      const lineProfileResult = await this.ctx.model.LineProfile.find({
        oltId: params.OltId,
      });
      await setRegisteredOnuAcsUrl(
        onuResult,
        oltResult,
        lineProfileResult,
        this
      );
      result.msg = 'setRegisteredOnuAcsUrl successful';
      result.flag = true;
      return result;
    } catch (error) {
      result.msg = 'setRegisteredOnuAcsUrl fail,' + error;
      result.flag = false;
      return result;
    }
  }
}

function diffDate(d1, d2) {
  return (d2 - d1) / (1000 * 60 * 60 * 24);
}
async function snmpGetInfo(input) {
  // 通过snmp拿信息
  try {
    // 从机器上获取olt Detail信息
    let oltInfo;
    const options = new ConnectOption(
      input.oltIP,
      input.initCommunity,
      input.snmpUDPPort,
      162,
      true,
      true,
      input.telnetTCPPort,
      input.oltManagementPassword,
      input.username,
      input.password
    );
    switch (input.oltType) {
      case 'FIBERHOME':
        oltInfo = {
          systemName: ''
        };
        break;
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        oltInfo = await xd.getOltInformation();
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        oltInfo = await zte.getOltInformation();
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        oltInfo = await hw.getOltInformation();
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        oltInfo = await xgl.getOltInformation();
        break;
    }
    return oltInfo;
  } catch (error) {
    throw error;
  }
}

async function insertOlt(input, result, me) {
  const olt = input;
  olt.id = ulid.ulid();
  const obj_olt = await me.ctx.model.Olt.create(olt);
  // advance创建默认信息
  const OltAdvanceInput = {
    id: ulid.ulid(),
    Use_DHCP_Option82: false,
    DHCP_Option82_field: '',
    Use_PPPoE_plus: false,
    ONU_IP_DHCP_Snooping: false,
    Use_max_mac_learn: false,
    Max_Macs_allowed_on_internet_vport_per_ONU: '10',
    Use_Mac_allow_list: false,
    Use_Mac_drop_list: false,
    Use_Ports_filtering_ACL: false,
    Ports_filtering_ACL: '',
    ONUs_signal_level_warning: '50',
    ONUs_signal_level_critical: '20',
    Use_CVLANID_option: false,
    Use_SVLANID_option: false,
    OltId: olt.id,
    tid: input.tid,
  };
  input.advance = await me.ctx.model.OltAdvance.create(OltAdvanceInput);
  result.id = obj_olt.id;
  return result;
}

async function setCommunity(input, me) {
  let arr = [];
  const communitys = [];
  const options = new ConnectOption(
    input.oltIP,
    input.snmpReadOnlyCommunity,
    input.snmpUDPPort,
    162,
    true,
    true,
    input.telnetTCPPort,
    input.oltManagementPassword,
    input.oltTelnetUsername,
    input.oltTelnetPassword,
    input.systemName,
    input.RZUsername,
    input.RZPassword
  );
  switch (input.oltType) {
    case 'OPTICTIMES':
      const xd = new XDOLT(options);
      arr = await xd.GetCommunity_XD(me);
      if (arr.length > 0) {
        // 只删除是我们系统里添加的团体名
        arr.forEach(community => {
          if (community.startsWith('RZ')) {
            communitys.push(community);
          }
        });
        await xd.DeleteCommunity_XD(communitys, me);
      }
      await xd.SetCommunity_XD(
        input.snmpReadOnlyCommunity,
        input.snmpReadWriteCommunity,
        me
      );
      break;
    case 'ZTE':
      const zte = new ZTEOLT(options);
      arr = await zte.GetCommunity_ZTE(me);
      if (arr.length > 0) {
        // 只删除是我们系统里添加的团体名
        arr.forEach(community => {
          if (community.startsWith('RZ')) {
            communitys.push(community);
          }
        });
        await zte.DeleteCommunity_ZTE(communitys, me);
      }
      await zte.SetCommunity_ZTE(
        input.snmpReadOnlyCommunity,
        input.snmpReadWriteCommunity,
        me
      );
      break;
    case 'HUAWEI':
      const hw = new HWOLT(options);
      arr = await hw.GetCommunity_HW(me); // 查询community数组
      if (arr.length > 0) {
        // 只删除是我们系统里添加的团体名
        arr.forEach(community => {
          if (community.startsWith('RZ')) {
            communitys.push(community);
          }
        });
        await hw.DeleteCommunity_HW(communitys, me);
      }
      await hw.SetCommunity_HW(
        input.snmpReadOnlyCommunity,
        input.snmpReadWriteCommunity,
        me
      );
      break;
    case 'XINGELIN':
      const xgl = new XGLOLT(options);
      arr = await xgl.GetCommunity_XGL(me);
      if (arr.length > 0) {
        arr.forEach(data => {
          if (data.community.startsWith('RZ')) {
            communitys.push(data.index);
          }
        });
        await xgl.DeleteCommunity_XGL(communitys, me);
      }
      await xgl.SetCommunity_XGL(
        input.snmpReadOnlyCommunity,
        input.snmpReadWriteCommunity,
        me
      );
      break;
  }
}

async function updateOlt(input, oltInfo, me) {
  try {
    const olt_obj = {
      systemName: oltInfo.systemName,
      serialNumber: oltInfo.serialNumber,
      macAddress: oltInfo.macAddress,
      softwareCreatedTime: oltInfo.softwareCreatedTime,
      systemTime: oltInfo.systemTime,
      runningTime: oltInfo.runningTime,
      cpuUsage: oltInfo.cpuUsage,
      memoryUsage: oltInfo.memoryUsage,
      licenseLimit: oltInfo.licenseLimit,
      licenseTime: oltInfo.licenseTime,
      oltHardVersion: oltInfo.hardwareVersion,
      oltSoftwareVersion: oltInfo.softwareVersion,
    };
    const a = await me.ctx.model.Olt.update(olt_obj, {
      where: {
        id: input.id
      },
    });
    if (a) {
      return true;
    }
  } catch (error) {
    throw error;
  }
}

async function TestConnect(options,ctx) {
  return new Promise(async (resolve, reject) => {
    let oids;
    if (options.oltType == 'OPTICTIMES') {
      oids = [
        '1.3.6.1.4.1.37950.1.1.5.10.12.5.1.0', // systemName
      ];
    } else {
      oids = [
        '1.3.6.1.2.1.1.5.0', // systemName
      ];
    }
    options.version = 1;
    const session = await createSession.call({ctx},this.options.ip,this.options.community,this.options);
    session.get(oids, function (error, varbinds) {
      if (error) {
        reject(error);
      } else {
        resolve(varbinds[0].value.toString());
      }
    });
  });
}
async function onuProfileRefresh(id, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const oltInformation = await me.ctx.model.Olt.findOne({
    where: {
      id
    }
  });
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let onuprofilearr;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        onuprofilearr = await xd.getOnuProfileList();
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        onuprofilearr = await zte.getOnuProfileList(
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    await me.ctx.model.OnuProfile.destroy({
      where: {
        oltId: id
      }
    });
    for (let i = 0; i < onuprofilearr.length; i++) {
      onuprofilearr[i].id = ulid.ulid();
      onuprofilearr[i].oltId = id;
    }
    await me.ctx.model.OnuProfile.bulkCreate(onuprofilearr);
    result.msg = 'onuprofilelist refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'onuprofilelist refresh fail';
    result.flag = false;
    return result;
  }
}
// 华为和新格林
async function lineProfileRefresh(id, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const oltInformation = await me.ctx.model.Olt.findOne({
    where: {
      id
    }
  });
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.snmpReadOnlyCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  try {
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        const hw = new HWOLT(options);
        const arr = await hw.getLineProfile(oltInformation.oltHardVersion, me);
        var lineprofilearr = await hw.getLineProfileMessage(
          oltInformation.oltHardVersion,
          arr,
          me
        );
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        var lineprofilearr = await xgl.getLineProfile(
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    await me.ctx.model.LineProfile.destroy({
      where: {
        oltId: id
      }
    });
    for (let i = 0; i < lineprofilearr.length; i++) {
      lineprofilearr[i].id = ulid.ulid();
      lineprofilearr[i].oltId = id;
    }
    await me.ctx.model.LineProfile.bulkCreate(lineprofilearr);
    result.flag = true;
    result.msg = 'lineprofilelist refresh successful';
    return result;
  } catch (error) {
    result.flag = false;
    result.msg = 'lineprofilelist refresh fail';
    return result;
  }
}
async function srvProfileRefresh(id, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const oltInformation = await me.ctx.model.Olt.findOne({
    where: {
      id
    }
  });
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let srvProfileResult;
  try {
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        const hw = new HWOLT(options);
        srvProfileResult = await hw.getSrvProfile(
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    await me.ctx.model.SrvProfile.destroy({
      where: {
        oltId: id
      }
    });
    for (let i = 0; i < srvProfileResult.length; i++) {
      srvProfileResult[i].id = ulid.ulid();
      srvProfileResult[i].oltId = id;
    }
    await me.ctx.model.SrvProfile.bulkCreate(srvProfileResult);
    result.flag = true;
    result.msg = 'srvprofile refresh successful';
    return result;
  } catch (error) {
    result.flag = false;
    result.msg = 'srvprofile refresh fail';
    return result;
  }
}
// 只有中兴
async function dbaProfileRefresh(id, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const oltInformation = await me.ctx.model.Olt.findOne({
    where: {
      id
    }
  });
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let arr;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        arr = await zte.getDbaProfile_ZTE(oltInformation.oltHardVersion, me);
        break;
    }
    await me.ctx.model.DbaProfile.destroy({
      where: {
        oltId: id
      }
    });
    for (let i = 0; i < arr.length; i++) {
      arr[i].id = ulid.ulid();
      arr[i].oltId = id;
    }
    await me.ctx.model.DbaProfile.bulkCreate(arr);
    result.msg = 'dbaprofilelist refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'dbaprofilelist refresh fail';
    result.flag = false;
    return result;
  }
}
// async function vlanTableRefresh(id, me) {
//   const result = {
//     msg: '',
//     flag:"",
//   };
//   const oltInformation = await me.ctx.model.Olt.findOne({ where: { id } });
//   const options = new ConnectOption(oltInformation.oltIP, oltInformation.snmpReadOnlyCommunity, oltInformation.snmpUDPPort, 162, true, true, oltInformation.telnetTCPPort, oltInformation.oltManagementPassword, oltInformation.oltTelnetUsername, oltInformation.oltTelnetPassword, oltInformation.systemName, oltInformation.snmpReadWriteCommunity);
//   let vlanarr;
//   try {
//     switch (oltInformation.oltType) {
//       case 'OPTICTIMES':
//         const xd = new XDOLT(options)
//         vlanarr = await xd.getVlanTable(); //从机器上获取vlantable
//         break;
//       case 'ZTE':
//         const ZTE = new ZTEOLT(options);
//         const vlanlist = await ZTE.getVlanTable(oltInformation.oltHardVersion, me);
//         //查询vlan描述
//         vlanarr = await ZTE.getVlanDesc(vlanlist,oltInformation.oltHardVersion,me)
//         break;
//       case 'HUAWEI':
//         const hw = new HWOLT(options)
//         const arr = await hw.getVlanTable(oltInformation.oltHardVersion,me);
//         //查询vlan描述
//         vlanarr = await hw.getVlanDesc(arr,oltInformation.oltHardVersion,me)
//         break;
//       case 'XINGELIN':
//         const xgl = new XGLOLT(options)
//         vlanarr = await xgl.getVlanTable(oltInformation.oltHardVersion,me)
//         break;
//     }
//     await me.ctx.model.Vlan.destroy({ where: { oltId: id } });
//     for (let i = 0; i < vlanarr.length; i++) {
//       if(vlanarr[i].VlanID.indexOf('-') != -1){
//         for(var j =vlanarr[i].VlanID.split('-')[0];j<=vlanarr[i].VlanID.split('-')[1];j++){
//           await me.ctx.model.Vlan.create({
//             id:ulid.ulid(),
//             oltId:id,
//             VlanID:j,
//             Memo:vlanarr[i].Memo,
//             uplinklist:vlanarr[i].uplinklist,
//             UsedForIPTV : false,
//             UsedForMgmt_VoIP : false,
//             DHCP_Snooping : false,
//             Lan2Lan : false,
//           })
//         }
//       }else{
//         await me.ctx.model.Vlan.create({
//           id:ulid.ulid(),
//           oltId:id,
//           VlanID:vlanarr[i].VlanID,
//           Memo:vlanarr[i].Memo,
//           uplinklist:vlanarr[i].uplinklist,
//           UsedForIPTV : false,
//           UsedForMgmt_VoIP : false,
//           DHCP_Snooping : false,
//           Lan2Lan : false,
//         })
//       }
//     }
//     result.msg = 'vlanTable refresh successful';
//     result.flag = true;
//     return result;
//   } catch (error) {
//     result.msg = 'vlanTable refresh fail';
//     result.msg = false;
//     return result;
//   }
// }
async function ponRefresh(id,oltInformation, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.snmpReadOnlyCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let ponarr,
    temp;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        temp = await xd.getPonPortList(this.ctx);
        ponarr = await xdmerge(temp);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        temp = await zte.getUplinkPortInfo(this.ctx);
        ponarr = await ztemerge(temp[0], temp[1]);
        // ponarr = await zte.getPonTx(arr, oltInformation.oltHardVersion, me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        temp = await hw.getUplinkPortInfo(this.ctx);
        ponarr = await hwmerge(temp[0], temp[1]);
        // ponarr = await hw.getPonTx(temp,oltInformation.oltHardVersion,me)
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        temp = await xgl.getPonPortList(this.ctx);
        ponarr = await xglmerge(temp);
        break;
    }
    for (let i = 0; i < ponarr.length; i++) {
      const a = await me.ctx.model.Onu.findAndCountAll({
        where: {
          oltId: id,
          S: ponarr[i].slot,
          P: ponarr[i].ifIndex
        },
      });
      ponarr[i].ONUs = a.count;
    }
    const ponarrResult = await getInputArray(
      oltInformation.oltType,
      ponarr,
      id
    );
    await me.ctx.model.PonPorts.destroy({
      where: {
        oltId: id
      }
    });
    await me.ctx.model.PonPorts.bulkCreate(ponarrResult);
    result.msg = 'PON refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'PON refresh fail';
    result.flag = false;
    return result;
  }
}
async function cardRefresh(id,oltInformation, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.snmpReadOnlyCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let cardResult;
  try {
    switch (oltInformation.oltType) {
      case 'XINGELIN':
        cardResult = '';
        break;
      case 'OPTICTIMES':
        // 芯德没有卡
        cardResult = '';
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        cardResult = await zte.getCard_ZTE(oltInformation.oltHardVersion, me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        var cardlist = await hw.getCard_HW(oltInformation.oltHardVersion, me);
        // 获取port数量
        cardResult = await hw.getPortNumber(
          cardlist,
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    await me.ctx.model.Card.destroy({
      where: {
        oltId: id
      }
    });
    for (let i = 0; i < cardResult.length; i++) {
      cardResult[i].id = ulid.ulid();
      cardResult[i].oltId = id;
      cardResult[i].role = 'Admin';
      cardResult[i].realType = cardResult[i].realType ?
        cardResult[i].realType :
        cardResult[i].cardType;
      cardResult[i].type = cardResult[i].cardType;
      cardResult[i].portNumber = cardResult[i].numberOfPorts;
      cardResult[i].softwareVersion = cardResult[i].softwateVersion;
      cardResult[i].status = cardResult[i].cardStatus;
    }
    await me.ctx.model.Card.bulkCreate(cardResult);
    result.msg = 'card refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'card refresh fail';
    result.flag = false;
    return result;
  }
}
async function uplinkRefresh(id,oltInformation, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.snmpReadOnlyCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let uplinkResult,
    res;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        var temp = await xd.getUplinkPortInfo(this.ctx); // 从机器上获取vlantable
        var uplinklist = await xdmerge2(temp[0], temp[1]);
        // 查询untag 和tag
        uplinkResult = await xd.getUplinkVlan(
          uplinklist,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        res = await zte.getUplinkPortInfo(this.ctx);
        var uplinklist = await uplinkPortData(res, oltInformation.oltType); // 组装数据
        // 查询speed，linkstatus和untag和tag
        uplinkResult = await zte.getUplinkSpeedAndVlan(
          uplinklist,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        res = await hw.getUplinkPortInfo(this.ctx); // 获取数据
        const uplinkport = await uplinkPortData(res, oltInformation.oltType); // 组装数据
        var arr = [];
        for (const item in uplinkport) {
          if (
            arr.indexOf(
              uplinkport[item].PortID.replace('etherent', '').split('/')[1]
            ) == -1
          ) {
            arr.push(
              uplinkport[item].PortID.replace('etherent', '').split('/')[1]
            );
          }
        }
        // 查询uplink linkstatus和是千||万兆网卡
        const firstUplinkResult = await hw.getUplinkStateAndSpeed(
          arr,
          uplinkport,
          oltInformation.oltHardVersion,
          me
        );
        uplinkResult = await hw.getUplinkVlan(
          firstUplinkResult,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        res = await xgl.getPonPortList(this.ctx);
        var uplinklist = await xglmerge2(res);
        // 查询uplink linkstatus和speed和tagvlan和untagvlan
        uplinkResult = await xgl.getUplinkSpeedAndVlan(
          uplinklist,
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    await me.ctx.model.Uplink.destroy({
      where: {
        oltId: id
      }
    });
    const uplinkDataResult = await uplinkData(
      uplinkResult,
      oltInformation.oltType,
      id
    );
    await me.ctx.model.Uplink.bulkCreate(uplinkDataResult);
    result.msg = 'uplink refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'uplink refresh fail';
    result.flag = false;
    return result;
  }
}

async function macRefresh(oltInformation, me) {
  const result = {
    msg: '',
    flag: true,
  };
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.snmpReadOnlyCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let macResult;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        macResult = await xd.getMacTable(); // 从机器上获取vlantable
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        macResult = await zte.getmacTable_ZTE(
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        macResult = await hw.getmacTable_HW(oltInformation.oltHardVersion, me);
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        macResult = await xgl.getmacTable_XGL(
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    if (macResult != null) {
      await me.ctx.model.Mac.destroy({
        where: {
          oltId: id
        }
      });
      for (let i = 0; i < macResult.length; i++) {
        (macResult[i].id = ulid.ulid()), (macResult[i].oltId = id);
      }
      await me.ctx.model.Mac.bulkCreate(macResult);
    }
    result.msg = 'mac refresh successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'mac refresh fail';
    result.flag = false;
    return result;
  }
}
async function getInputArray(oltType, ponPortsArray, oltId) {
  const inputArray = [];
  switch (oltType) {
    case 'FIBERHOME':
      ponPortsArray.sort((a, b) => {
        const x = parseInt(a.port);
        const y = parseInt(b.port);
        return x - y;
      });
      ponPortsArray.forEach((element, index) => {
        inputArray.push({
          id: ulid.ulid(),
          SlotIndex: element.slot,
          port: element.pon,
          BoardType: '',
          Type: element.portType,
          AdminState: element.status,
          Status: element.status,
          ONUOnlineNumber: element.ONUs,
          ONUTotalNumber: element.ONUs,
          Memo: '',
          minRange: element.portDownlinkRate,
          maxRange: element.portUplinkRate,
          TXPower: element.TXPower,
          Temperature: '',
          Voltage: '',
          BiasCurrent: '',
          oltId,
          num: index,
          tid: '',
        });
      });
      break;
    case 'OPTICTIMES':
      ponPortsArray.sort((a, b) => {
        const x = parseInt(a.port);
        const y = parseInt(b.port);
        return x - y;
      });
      ponPortsArray.forEach((element, index) => {
        inputArray.push({
          id: ulid.ulid(),
          SlotIndex: element.slot,
          port: element.port,
          BoardType: '',
          Type: '',
          AdminState: element.status,
          Status: element.status,
          ONUOnlineNumber: element.ONUs,
          ONUTotalNumber: element.ONUs,
          Memo: '',
          minRange: '0',
          maxRange: '20000',
          TXPower: element.transmitPower,
          Temperature: element.temperature,
          Voltage: element.voltage,
          BiasCurrent: element.biasCurrent,
          oltId,
          num: index,
          tid: '',
        });
      });
      break;
    case 'ZTE':
      ponPortsArray.sort((a, b) => {
        const slotA = a.slot;
        const slotB = b.slot;
        const indexArrA = a.port.split('_')[1].split('/');
        const indexArrB = b.port.split('_')[1].split('/');
        const r_A =
          parseInt(slotA) * 1000000 +
          parseInt(indexArrA[0]) * 10000 +
          parseInt(indexArrA[1]) * 100 +
          parseInt(indexArrA[2]);
        const r_B =
          parseInt(slotB) * 1000000 +
          parseInt(indexArrB[0]) * 10000 +
          parseInt(indexArrB[1]) * 100 +
          parseInt(indexArrB[2]);
        return r_A - r_B;
      });
      ponPortsArray.forEach((element, index) => {
        inputArray.push({
          id: ulid.ulid(),
          SlotIndex: element.slot,
          port: element.port,
          BoardType: '',
          Type: element.type,
          AdminState: element.status,
          Status: element.status,
          ONUOnlineNumber: element.ONUs,
          ONUTotalNumber: element.ONUs,
          Memo: '',
          minRange: '0',
          maxRange: '20000',
          TXPower: element.TXPower,
          Temperature: 'N/A',
          Voltage: 'N/A',
          BiasCurrent: 'N/A',
          oltId,
          num: index,
          tid: '',
        });
      });
      break;
    case 'HUAWEI':
      ponPortsArray.sort((a, b) => {
        const slotA = a.slot;
        const slotB = b.slot;
        const r_A = parseInt(slotA) * 1000000 + parseInt(a.port) * 10000;
        const r_B = parseInt(slotB) * 1000000 + parseInt(b.port) * 10000;
        return r_A - r_B;
      });
      ponPortsArray.forEach((element, index) => {
        inputArray.push({
          id: ulid.ulid(),
          SlotIndex: element.slot,
          port: element.port,
          BoardType: '',
          Type: element.type,
          AdminState: element.status,
          Status: element.status,
          ONUOnlineNumber: element.ONUs,
          ONUTotalNumber: element.ONUs,
          Memo: '',
          minRange: '0',
          maxRange: '20000',
          TXPower: element.TXPower,
          Temperature: 'N/A',
          Voltage: 'N/A',
          BiasCurrent: 'N/A',
          oltId,
          num: index,
          tid: '',
        });
      });
      break;
    case 'XINGELIN':
      ponPortsArray.sort((a, b) => {
        const x = parseInt(a.port);
        const y = parseInt(b.port);
        return x - y;
      });
      ponPortsArray.forEach((element, index) => {
        inputArray.push({
          id: ulid.ulid(),
          SlotIndex: element.slot,
          port: element.port,
          BoardType: '',
          Type: element.type,
          AdminState: element.status,
          Status: element.status,
          ONUOnlineNumber: element.ONUs,
          ONUTotalNumber: element.ONUs,
          Memo: '',
          minRange: '0',
          maxRange: '20000',
          TXPower: element.TXPower,
          Temperature: element.temperature,
          Voltage: element.voltage,
          BiasCurrent: element.biasCurrent,
          oltId,
          num: index,
          tid: '',
        });
      });
      break;
  }
  return inputArray;
}

async function uplinkPortData(tables, OltType) {
  switch (OltType) {
    case 'ZTE':
      return zte();
      break;
    case 'HUAWEI':
      return hw();
      break;
    case 'XINGELIN':
      return xgl();
      break;
  }

  function zte() {
    const arr = {};
    const table1 = tables[0];
    const table2 = tables[1];
    for (const key in table2) {
      if (table1[key][1].toString().indexOf('gei') != -1) {
        // ethernetCsmacd认为是uplink
        arr['GE' + table1[key][1].toString()] = {
          // PortID: table1[table2[key][1].toString()][1].toString(),
          PortID: table1[key][1].toString(),
          AdminStatus: table2[key][7].toString(),
          // 所有的linkstatus 取的是 adminstatus 1是up 2是down 在olt里面up是active down是deactive
          // LinkStatus: table2[key][7],
          // Speed: table2[key][5].toString(),
          // RxBytes: parseInt(table2[key][10]).toString(),
          // TxBytes: parseInt(table2[key][16]).toString(),
          // Errors: parseInt(table2[key][20]).toString(),
          RxPackets: 'N/A',
          RxUnicast: 'N/A',
          RxBroadcast: 'N/A',
          RxMulticast: 'N/A',
          TxPackets: 'N/A',
          TxUnicast: 'N/A',
          TxBroadcast: 'N/A',
          TxMulticast: 'N/A',
          Collisions: 'N/A',
        };
      }
    }
    return arr;
  }

  function hw() {
    const arr = {};
    const table1 = tables[0];
    const table2 = tables[1];
    for (const key in table1) {
      if (table1[key][1].toString().indexOf('ethernet') != -1) {
        // ethernetCsmacd认为是uplink
        arr[table1[key][1].toString()] = {
          PortID: table1[key][1].toString().replace('ethernet', ''),
          AdminStatus: table2[key][7].toString(),
          // Speed: table2[key][5].toString(),
          // RxBytes: parseInt(table2[key][10]).toString(),
          // TxBytes: parseInt(table2[key][16]).toString(),
          // Errors: parseInt(table2[key][20]).toString(),
          RxPackets: 'N/A',
          RxUnicast: 'N/A',
          RxBroadcast: 'N/A',
          RxMulticast: 'N/A',
          TxPackets: 'N/A',
          TxUnicast: 'N/A',
          TxBroadcast: 'N/A',
          TxMulticast: 'N/A',
          Collisions: 'N/A',
        };
      }
    }
    return arr;
  }

  function xgl() {
    const arr = {};
    const table1 = tables[0];
    const table2 = tables[1];
    for (const key in table1) {
      if (table1[key][1].toString().indexOf('e') != -1) {
        // ethernetCsmacd认为是uplink
        arr[table1[key][1].toString()] = {
          PortID: table1[key][1].toString(),
          AdminStatus: table2[key][7].toString(),
          // Speed: table2[key][5].toString(),
          // RxBytes: parseInt(table2[key][10]).toString(),
          // TxBytes: parseInt(table2[key][16]).toString(),
          // Errors: parseInt(table2[key][20]).toString(),
          RxPackets: 'N/A',
          RxUnicast: 'N/A',
          RxBroadcast: 'N/A',
          RxMulticast: 'N/A',
          TxPackets: 'N/A',
          TxUnicast: 'N/A',
          TxBroadcast: 'N/A',
          TxMulticast: 'N/A',
          Collisions: 'N/A',
        };
      }
    }
    return arr;
  }
}
async function uplinkData(uplinkObj, oltType, oltId) {
  const arr = [];
  for (const item in uplinkObj) {
    arr.push(uplinkObj[item]);
  }
  const inputArray = [];
  switch (oltType) {
    case 'FIBERHOME':
      break;
    case 'OPTICTIMES':
      arr.sort((a, b) => {
        const x = parseInt(a.PortID);
        const y = parseInt(b.PortID);
        return x - y;
      });
      break;
    case 'ZTE':
      arr.sort((a, b) => {
        const indexArrA = a.PortID.split('_')[1].split('/');
        const indexArrB = b.PortID.split('_')[1].split('/');
        const r_A =
          parseInt(indexArrA[0]) * 10000 +
          parseInt(indexArrA[1]) * 100 +
          parseInt(indexArrA[2]);
        const r_B =
          parseInt(indexArrB[0]) * 10000 +
          parseInt(indexArrB[1]) * 100 +
          parseInt(indexArrB[2]);
        return r_A - r_B;
      });
      break;
    case 'HUAWEI':
      arr.sort((a, b) => {
        const indexArrA = a.PortID.replace('ethernet', '').split('/');
        const indexArrB = b.PortID.replace('ethernet', '').split('/');
        const r_A =
          parseInt(indexArrA[0]) * 10000 +
          parseInt(indexArrA[1]) * 100 +
          parseInt(indexArrA[2]);
        const r_B =
          parseInt(indexArrB[0]) * 10000 +
          parseInt(indexArrB[1]) * 100 +
          parseInt(indexArrB[2]);
        return r_A - r_B;
      });
      break;
    case 'XINGELIN':
      arr.sort((a, b) => {
        const x = parseInt(a.PortID);
        const y = parseInt(b.PortID);
        return x - y;
      });
      break;
  }
  arr.forEach((element, index) => {
    inputArray.push({
      id: ulid.ulid(),
      PortID: element.PortID,
      Speed: element.Speed,
      AdminStatus: element.AdminStatus,
      LinkStatus: element.LinkStatus,
      Tagvlan: element.Tagvlan,
      UnTagvlan: element.UnTagvlan,
      oltId,
      num: index,
    });
  });
  return inputArray;
}
async function OltSave(id, me) {
  const result = {
    msg: '',
    flag: true,
  };
  let oltInformation = await this.ctx.service.common.getOltInfo(params.OltId);
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  ); 
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        await xd.saveOlt(oltInformation.oltHardVersion, me);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        await zte.saveOlt(oltInformation.oltHardVersion, me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        await hw.saveOlt(oltInformation.oltHardVersion, me);
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        await xgl.saveOlt(oltInformation.oltHardVersion, me);
        break;
    }
    result.msg = 'olt save successful';
    result.flag = true;
    return result;
  } catch (error) {
    result.msg = 'olt save fail,' + error;
    result.flag = false;
    return result;
  }
}
async function xdmerge(arr) {
  const result = [];
  for (const i in arr) {
    result.push({
      ifIndex: arr[i][1].toString(),
      slot: 1,
      port: arr[i][1].toString(),
      status: arr[i][3].toString(),
    });
  }
  return result;
}
async function xdmerge2(arr1, arr2) {
  const arr = [];
  for (const i in arr1) {
    if (arr1[i][18].toString() == '1') {
      var UnTagvlan = '';
    } else {
      var UnTagvlan = arr1[i][18].toString();
    }
    if (arr1[i][4].toString() == '1') {
      var AdminStatus = 1;
    } else {
      var AdminStatus = 2;
    }
    arr.push({
      PortID: arr1[i][1].toString(),
      LinkStatus: arr2[i][2].toString(),
      Speed: arr2[i][3].toString(),
      AdminStatus,
      UnTagvlan,
    });
  }
  return arr;
}
async function xglmerge(arr) {
  const result = [];
  for (const i in arr) {
    if (arr[i][2].toString().indexOf('g0') != -1) {
      result.push({
        ifIndex: arr[i][2].toString().split('/')[1],
        slot: arr[i][2].toString().replace('g', '').split('/')[0],
        port: arr[i][2].toString().split('/')[1],
        status: arr[i][7].toString(),
      });
    }
  }
  return result;
}
async function xglmerge2(arr) {
  const result = [];
  for (const i in arr) {
    if (arr[i][2].toString().indexOf('e') != -1) {
      result.push({
        PortID: arr[i][2].toString(),
        AdminStatus: arr[i][7].toString(),
      });
    }
  }
  return result;
}
//-----------------------------------------------------------------------------------
async function isOnline(oltInformation,me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let result = false;
  switch (oltInformation.oltType) {
    case 'FIBERHOME':
      break;
    case 'OPTICTIMES':
      const xd = new XDOLT(options);
      result = await xd.XDTestConnection();
      break;
    case 'ZTE':
      const zte = new ZTEOLT(options);
      result = await zte.ZTETestConnection(me);
      break;
    case 'HUAWEI':
      const hw = new HWOLT(options);
      result = await hw.HWTestConnection(me);
      break;
    case 'XINGELIN':
      const xgl = new XGLOLT(options);
      result = await xgl.XGLTestConnection();
      break;
  }
  return result;
}
async function snmpGetSystenName(oltInformation) {
  try {
    // 从机器上获取olt Detail信息
    let oltInfo;
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    switch (oltInformation.oltType) {
      case 'FIBERHOME':
        oltInfo = {
          systemName: ''
        };
        break;
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        oltInfo = await xd.getOltSystemName(this.ctx);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        oltInfo = await zte.getOltSystemName(this.ctx);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        oltInfo = await hw.getOltSystemName(this.ctx);
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        oltInfo = await xgl.getOltSystemName(this.ctx);
        break;
    }
    return oltInfo;
  } catch (error) {
    throw error;
  }
}
async function setRZAdmin(oltInformation, me) {
  try {
    let createResult;
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    switch (oltInformation.oltType) {
      case 'FIBERHOME':
        break;
      case 'OPTICTIMES':
        const xd = new XDOLT(options);
        createResult = await xd.setRZAdmin();
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        createResult = await zte.setRZAdmin(me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        createResult = await hw.setRZAdmin(me);
        break;
      case 'XINGELIN':
        const xgl = new XGLOLT(options);
        createResult = await xgl.setRZAdmin();
        break;
    }
    return createResult;
  } catch (error) {
    throw error;
  }
}
async function getOltVersion(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
  );
  let oltVersionResult;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        oltVersionResult = await zte.getOltVersion(me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        oltVersionResult = await hw.getOltVersion(me);
        break;
    }
    return oltVersionResult;
  } catch (error) {
    throw error;
  }
}
async function getOltInformation(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let oltInformationResult;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        oltInformationResult = await zte.getOltInformation(
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        oltInformationResult = await hw.getOltInformation(
          oltInformation.MCIndex,
          me
        );
        break;
    }
    return oltInformationResult;
  } catch (error) {
    throw error;
  }
}
async function getOltTemperature(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let result;
  try {
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        // 获取olt温度
        const hw = new HWOLT(options);
        result = await hw.getOltTemperature(oltInformation.MCIndex, me);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        result = await zte.getOltTemperature(
          oltInformation.oltHardVersion,
          oltInformation.MCIndex,
          me
        );
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function getCardInformation(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
  );
  let result;
  try {
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        const hw = new HWOLT(options);
        // 先获取卡列表
        result = await hw.getCardInformation(me);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        result = await zte.getCardInformation(
          oltInformation.oltHardVersion,
          me
        );
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function getPonPortsAndUplinkPorts(oltInformation) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
  );
  let portlist,
    result;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        portlist = await zte.getPonPortsAndUplinkPorts(this.ctx);
        result = ztemerge(portlist[0], portlist[1]);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        portlist = await hw.getPonPortsAndUplinkPorts(this.ctx);
        result = hwmerge(portlist[0], portlist[1]);
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}

function  ztemerge(arr1, arr2) {
  const result = {
    ponPortsArr: [],
    uplinkPortsArr: [],
  };
  for (const i in arr1) {
    if (arr1[i][1].toString().indexOf('gpon') != -1) {
      result.ponPortsArr.push({
        port: arr1[i][1].toString(),
        p: arr1[i][1].toString().split('/')[1],
        s: arr1[i][1].toString().split('/')[2],
        adminStatus: arr2[i][7].toString() == '1' ? 'up' : 'down',
        status: arr2[i][8].toString() == '1' ? 'up' : 'down',
      });
    } else if (arr1[i][1].toString().indexOf('gei') != -1) {
      var speed
      if(arr2[i][5] == 0){
        speed = "auto"
      }else if(arr2[i][5] == 4294967295){
        speed = 10000
      }else {
        speed = arr2[i][5] / 1000000
      }
      result.uplinkPortsArr.push({
        port: arr1[i][1].toString(),
        p: arr1[i][1].toString().split('/')[1],
        s: arr1[i][1].toString().split('/')[2],
        speed,
        adminStatus: arr2[i][7].toString() == '1' ? 'up' : 'down',
        status: arr2[i][8].toString() == '1' ? 'up' : 'down',
      });
    }
  }
  return result;
}

function hwmerge(arr1, arr2) {
  const result = {
    ponPortsArr: [],
    uplinkPortsArr: [],
  };
  for (const i in arr1) {
    if (arr1[i][1].toString().indexOf('GPON') != -1) {
      let status;
      if (arr2[i][8].toString() == '1') {
        status = 'up';
      } else if (arr2[i][8].toString() == '2') {
        status = 'down';
      } else if (arr2[i][8].toString() == '6') {
        status = 'notPresent';
      }
      result.ponPortsArr.push({
        port: arr1[i][1].toString(),
        p: arr1[i][1].toString().split('/')[1],
        s: arr1[i][1].toString().split('/')[2],
        adminStatus: arr2[i][7].toString() == '1' ? 'up' : 'down',
        status,
        // status:arr2[i][8].toString()=="1"?"up":"down",
      });
    } else if (arr1[i][1].toString().indexOf('ether') != -1) {
      let status;
      if (arr2[i][8].toString() == '1') {
        status = 'up';
      } else if (arr2[i][8].toString() == '2') {
        status = 'down';
      } else if (arr2[i][8].toString() == '6') {
        status = 'notPresent';
      }
      result.uplinkPortsArr.push({
        port: arr1[i][1].toString(),
        p: arr1[i][1].toString().split('/')[1],
        s: arr1[i][1].toString().split('/')[2],
        speed: arr2[i][5] == 4294967295 ? 10000 : arr2[i][5] / 1000000,
        adminStatus: arr2[i][7].toString() == '1' ? 'up' : 'down',
        status,
        // status:arr2[i][8].toString()=="1"?"up":"down",
      });
    }
  }
  return result;
}
async function getOltONUProfile(oltInformation, me) {
  try {
    let onuprofilearr;
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        onuprofilearr = await zte.getOnuProfileList(
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        onuprofilearr = await hw.getSrvProfileList(me);
        break;
    }
    return onuprofilearr;
  } catch (error) {
    throw error;
  }
}
async function getOltDBAProfile(oltInformation, me) {
  try {
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    let arr;
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        arr = await zte.getDBAProfileList(oltInformation.oltHardVersion, me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        let dbalist = await hw.getDBAProfileList(me);
        arr = await hw.getDBAProfile(dbalist, me)
        break;
    }
    return arr;
  } catch (error) {
    throw error;
  }
}
async function getOltRemoteDetail(lines,oltInformation,me){
  try {
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    let arr;
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options)
        arr = await zte.getOltRemoteProfileDetail(lines,oltInformation.oltHardVersion, me);
        break;
    }
    return arr;
  } catch (error) {
    throw error;
  }
}
async function getOltLineDetail(lines,oltInformation,me){
  try {
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    let arr;
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        const hw = new HWOLT(options);
        arr = await hw.getLineProfileMessage("NONE",lines,me);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options)
        arr = await zte.getOltLineProfileDetail(lines,oltInformation.oltHardVersion, me);
        break;
    }
    return arr;
  } catch (error) {
    throw error;
  }
}
async function getOltLineProfile(oltInformation, me) {
  try {
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    let arr;
    switch (oltInformation.oltType) {
      case 'HUAWEI':
        const hw = new HWOLT(options);
        arr = await hw.getOltLineProfile(me);
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options)
        arr = await zte.getOltLineProfile(oltInformation.oltHardVersion, me);
        break;
    }
    return arr;
  } catch (error) {
    throw error;
  }
}
async function getOltRemoteProfile(oltInformation, me) {
  try {
    const options = new ConnectOption(
      oltInformation.oltIP,
      oltInformation.initCommunity,
      oltInformation.snmpUDPPort,
      162,
      true,
      true,
      oltInformation.telnetTCPPort,
      oltInformation.oltManagementPassword,
      oltInformation.oltTelnetUsername,
      oltInformation.oltTelnetPassword,
      oltInformation.systemName,
      oltInformation.RZUsername,
      oltInformation.RZPassword,
      oltInformation.telnetProxySwitch
    );
    let arr;
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options)
        arr = await zte.getOltRemoteProfile(oltInformation.oltHardVersion, me);
        break;
    }
    return arr;
  } catch (error) {
    throw error;
  }
}
async function getOltVlan(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let vlanarr;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        // const xd = new XDOLT(options)
        // vlanarr = await xd.getVlanTable(); //从机器上获取vlantable
        break;
      case 'ZTE':
        const ZTE = new ZTEOLT(options);
        vlanarr = await ZTE.getOltVlan(oltInformation.oltHardVersion, me);
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        vlanarr = await hw.getOltVlan(me);
        break;
      case 'XINGELIN':
        // const xgl = new XGLOLT(options)
        // vlanarr = await xgl.getVlanTable(oltInformation.oltHardVersion,me)
        break;
    }
    return vlanarr;
  } catch (error) {
    throw error;
  }
}
async function getOltMac(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let macResult;
  try {
    switch (oltInformation.oltType) {
      case "ZTE":
        const zte = new ZTEOLT(options);
        macResult = await zte.getOltMac(oltInformation.oltHardVersion, me)
        break;
      case "HUAWEI":
        const hw = new HWOLT(options);
        macResult = await hw.getOltMac(me)
        break;
    }
    return macResult;
  } catch (error) {
    throw error
  }
}
async function getOltSpeedProfile(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let speedProfileResult;
  try {
    switch (oltInformation.oltType) {
      case 'OPTICTIMES':
        break;
      case 'ZTE':
        const zte = new ZTEOLT(options);
        speedProfileResult = await zte.getOltSpeedProfile(
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        const speedProfileInexResult = await hw.getOltSpeedProfileIndex(me);
        speedProfileResult = await hw.getOltSpeedProfile(
          speedProfileInexResult,
          me
        );
        break;
      case 'XINGELIN':
        break;
    }
    return speedProfileResult;
  } catch (error) {
    throw error;
  }
}
async function setOltAcsVlan(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let result;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        result = await zte.setOltAcsVlan(
          oltInformation.ACSVlan,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        result = await hw.setOltAcsVlan(oltInformation.ACSVlan, me);
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function getRegisteredONUList(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let onuList,
    result;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        onuList = await zte.getOnuList(oltInformation.oltHardVersion, me);
        // result = await zte.getOnuListMsg(
        //   onuList,
        //   oltInformation.oltHardVersion,
        //   me
        // )
        //刷新onudetail
        result = await zte.getOnuListMsg1(
          onuList,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        result = await hw.getOnuListMsg(me);
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function getUnregisteredONUList(oltInformation, me) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let result;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE': {
        const zte = new ZTEOLT(options);
        result = await zte.getUnregisteredONUList(
          oltInformation.oltHardVersion,
          me
        );
        break;
      }
      case 'HUAWEI': {
        const hw = new HWOLT(options);
        result = await hw.getUnregisteredONUList(me);
        break;
      }
      default:
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function sortONUFindIndex(oltType, oltID, tid, result, me) {
  let ponindex = '';
  let j = 0;
  for (let i = 0; i < result.length; i++) {
    if (ponindex != result[i].PONindex) {
      j = 0;
      ponindex = result[i].PONindex;
      result[i].ONUindex = await setONUindex(
        oltType,
        oltID,
        result[i].PONindex,
        j,
        me
      );
      result[i].number = result[i].ONUindex;
      j++;
    } else {
      result[i].ONUindex = await setONUindex(
        oltType,
        oltID,
        result[i].PONindex,
        j,
        me
      );
      result[i].number = result[i].ONUindex;
      j++;
    }
    result[i]._id = ulid.ulid();
    result[i].oltId = oltID;
    result[i].tid = tid;
  }
  return result;
}
async function setONUindex(oltType, oltID, PONindex, index, me) {
  let result;
  const onulistarr = [];
  const arr = [];
  const delta1 = oltType == 'HUAWEI' ? 0 : 1;
  const delta2 = oltType == 'HUAWEI' ? 127 : 128;
  for (let i = delta1; i <= delta2; i++) {
    arr.push(i);
  }
  const Onu = await me.ctx.model.OnuList.find({
    oltId: oltID,
    PONindex
  }).sort(
    'number'
  );
  for (let j = 0; j < Onu.length; j++) {
    onulistarr.push(parseInt(Onu[j].ONUindex)); // 数据库里的ONUindex
  }
  const remainArr = getSubArray(arr, onulistarr);
  result = remainArr[index];
  return result;
}

function getSubArray(arr1, arr2) {
  const set1 = new Set(arr1);
  const set2 = new Set(arr2);
  const result = [];
  set1.forEach((item, index) => {
    if (!set2.has(item)) {
      result.push(item);
    }
  });
  return result;
}
async function setRegisteredOnuAcsUrl(
  onuListResult,
  oltInformation,
  lineProfileResult,
  me
) {
  const options = new ConnectOption(
    oltInformation.oltIP,
    oltInformation.initCommunity,
    oltInformation.snmpUDPPort,
    162,
    true,
    true,
    oltInformation.telnetTCPPort,
    oltInformation.oltManagementPassword,
    oltInformation.oltTelnetUsername,
    oltInformation.oltTelnetPassword,
    oltInformation.systemName,
    oltInformation.RZUsername,
    oltInformation.RZPassword,
    oltInformation.telnetProxySwitch
  );
  let result;
  try {
    switch (oltInformation.oltType) {
      case 'ZTE':
        const zte = new ZTEOLT(options);
        // 先查询onulist列表
        // let onuListResult = await zte.getOnuList(oltInformation.oltHardVersion,me)
        // 再给已注册的onu下发acs地址
        result = await zte.setRegisteredOnuAcsUrl(
          onuListResult,
          oltInformation.ACSVlan,
          oltInformation.oltHardVersion,
          me
        );
        break;
      case 'HUAWEI':
        const hw = new HWOLT(options);
        // 先把lineprofile开启tr069
        await hw.setLineProfileTr069(lineProfileResult, me);
        // 然后给onu下发acs地址
        result = await hw.setRegisteredOnuAcsUrl(
          onuListResult,
          oltInformation.ACSVlan,
          me
        );
        break;
    }
    return result;
  } catch (error) {
    throw error;
  }
}
async function formatSeconds(time) {
  let theTime = parseInt(time); // 需要转换的时间秒
  theTime = Math.floor(theTime / 100);
  let theTime1 = 0; // 分
  let theTime2 = 0; // 小时
  let theTime3 = 0; // 天
  if (theTime > 60) {
    theTime1 = parseInt(theTime / 60);
    theTime = parseInt(theTime % 60);
    if (theTime1 > 60) {
      theTime2 = parseInt(theTime1 / 60);
      theTime1 = parseInt(theTime1 % 60);
      if (theTime2 > 24) {
        // 大于24小时
        theTime3 = parseInt(theTime2 / 24);
        theTime2 = parseInt(theTime2 % 24);
      }
    }
  }
  let result = '';
  if (theTime > 0) {
    // seconds
    result = '' + parseInt(theTime) + 's';
  }
  if (theTime1 > 0) {
    // minutes
    result = '' + parseInt(theTime1) + 'm' + result;
  }
  if (theTime2 > 0) {
    // hours
    result = '' + parseInt(theTime2) + 'h' + result;
  }
  if (theTime3 > 0) {
    // days
    result = '' + parseInt(theTime3) + 'd' + result;
  }
  return result;
}

module.exports = OltService;